package com.ajavaer.framework.core.request;

import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import javax.persistence.criteria.CriteriaBuilder.In;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

public class RequestSpecification<T> implements Specification<T> {
    private Collection<RequestFilter> filters;

    public RequestSpecification(Collection<RequestFilter> filters) {
        this.filters = filters;
    }

    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
                                 CriteriaBuilder builder) {
        if (filters != null && !filters.isEmpty()) {
            List<Predicate> predicates = new ArrayList<Predicate>();
            for (RequestFilter filter : filters) {
                // nested path translate, 如Task的名为"user.name"的filedName, 转换为Task.user.name属性
                String[] names = filter.fieldName.split("\\.");
                Path expression = root.get(names[0]);
                for (int i = 1; i < names.length; i++) {
                    expression = expression.get(names[i]);
                }

                switch (filter.operator) {
                    case EQ:
                        predicates.add(builder.equal(expression, filter.value));
                        break;
                    case NE:
                        predicates.add(builder.notEqual(expression, filter.value));
                        break;
                    case LIKE:
                        predicates.add(builder.like(expression, "%" + filter.value + "%"));
                        break;
                    case GT:
                        predicates.add(builder.greaterThan(expression, (Comparable) filter.value));
                        break;
                    case LT:
                        predicates.add(builder.lessThan(expression, (Comparable) filter.value));
                        break;
                    case GTE:
                        predicates.add(builder.greaterThanOrEqualTo(expression, (Comparable) filter.value));
                        break;
                    case LTE:
                        predicates.add(builder.lessThanOrEqualTo(expression, (Comparable) filter.value));
                        break;
                    case ISNULL:
                        predicates.add(builder.isNull(expression));
                        break;
                    case ISNOTNULL:
                        predicates.add(builder.isNotNull(expression));
                        break;
                    case IN:
                        Collection value = (Collection) filter.value;
                        Iterator iterator = value.iterator();
                        In in = builder.in(expression);
                        while (iterator.hasNext()) {
                            in.value(iterator.next());
                        }
                        predicates.add(in);
                        break;
                }
            }

            // 将所有条件用 and 联合起来
            if (predicates.size() > 0) {
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        }

        return builder.conjunction();
    }

}
